package org.ktjiaoyu.config;

import jakarta.annotation.Resource;
import org.ktjiaoyu.handel.MyAccessDeniedHandler2;
import org.ktjiaoyu.handel.MyFormLoginSuccessHandler;
import org.ktjiaoyu.service.impl.MyUserDetailsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.ProviderManager;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;

import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;

import javax.sql.DataSource;

/**
 * @author Jane
 * @date 2025-02-11 14:12
 */
@Configuration
public class SecurityConfig {

    @Autowired
    DataSource dataSource;

    @Autowired
    MyAccessDeniedHandler2 myAccessDeniedHandler;



    //记住我 具体存储到那个库和表
    @Bean
    public PersistentTokenRepository persistentTokenRepository(){
        JdbcTokenRepositoryImpl obj = new JdbcTokenRepositoryImpl();
        obj.setDataSource(dataSource);
        //启动创建表persistent_logs表，存token，username时会用到
        //如果token表不存在，使用下面语句可以初始化该表；若存在，请注释掉这条语句，否则会报错。
        obj.setCreateTableOnStartup(false);
        return obj;
    }

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http, MyUserDetailsService userDetailsService) throws Exception {

        //自定义登录页面
        http.formLogin(form->form.loginPage("/tologin")
                .loginProcessingUrl("/aaaa")
                .successForwardUrl("/doLogin")//单个的url
                //跳转到处理器重,可以 写更复杂的逻辑
                //.successHandler(new MyFormLoginSuccessHandler("/doLogin"))
                .permitAll()) ;//配置登录的表单相关的内容

        //记住我的  自定义配置
        //me.rememberMeParameter("abc") 改表单中记住我的那个□的name值
        http.rememberMe(me->me.rememberMeParameter("rme")
                .tokenValiditySeconds(60)
                .userDetailsService(userDetailsService)
                .tokenRepository(persistentTokenRepository())
        );

        //授权
        http.authorizeHttpRequests(authz->authz.requestMatchers("/tologin").permitAll()
               // .requestMatchers("/**.html").permitAll()
                //.requestMatchers("/toMain1").hasAnyAuthority("abcd","ddd")
              //  .requestMatchers("/toMain1").hasAnyRole("abcd")
                .anyRequest().authenticated()  //其他所有的请求必须要认证(登录)通过才能访问
        ).httpBasic(Customizer.withDefaults());


        //异常处理
        //自定义异常处理方案, 默认去security error的请求
//        http.exceptionHandling(ex->ex.accessDeniedHandler(new MyAccessDeniedHandler()));
        http.exceptionHandling(ex->ex.accessDeniedHandler(myAccessDeniedHandler));

        http.csrf(AbstractHttpConfigurer::disable);
        return http.build();//
    }

    @Resource
    MyUserDetailsService myUserDetailsService;
    @Bean
    public AuthenticationManager authenticationManager(PasswordEncoder passwordEncoder) {

        DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
        //将编写的UserDetailsService注入进来
        provider.setUserDetailsService(myUserDetailsService);
        //将使用的密码编译器加入进来
        provider.setPasswordEncoder(passwordEncoder);
        //将provider放置到AuthenticationManager 中
        ProviderManager providerManager = new ProviderManager(provider);

        return providerManager;
    }
}
